#pragma once
#include <functional>
#include <memory>
#include "fields.hpp"

namespace NightCord
{

    class BaseMessage
    {
    public:
        using ptr = std::shared_ptr<BaseMessage>;
        virtual ~BaseMessage() {}
        virtual void setId(const std::string &id)
        {
            _rid = id;
        }

        virtual std::string rid()
        {
            return _rid;
        }

        virtual void setMType(const MType &type)
        {
            _mtype = type;
        }

        virtual MType mtype()
        {
            return _mtype;
        }

        virtual std::string serialize() = 0;                  // 序列化
        virtual bool unserialize(const std::string &msg) = 0; // 反序列化
        virtual bool check() = 0;                             // 确认消息

    private:
        MType _mtype;     // 消息的类型
        std::string _rid; // 消息id
    };

    class BaseBuffer
    {
    public:
        using ptr = std::shared_ptr<BaseBuffer>;
        virtual size_t readableSize() = 0; // 可读空间
        virtual int32_t peekInt32() = 0;   // 读取4字节数据，但不消除
        virtual void retrieveInt32() = 0;  // 消除4字节数据
        virtual int32_t readInt32() = 0;   // 读取并消除4字节数据
        virtual std::string retireveAsString(size_t len) = 0;
    };

    class BaseProtocol
    {
    public:
        using ptr = std::shared_ptr<BaseProtocol>;
        virtual bool canProcessed(const BaseBuffer::ptr buf) = 0;                    // 判断能否执行
        virtual bool OnMessage(const BaseBuffer::ptr buf, BaseMessage::ptr msg) = 0; // 执行
        virtual std::string serialize(const BaseMessage::ptr &msg) = 0;
    };

    class BaseConnection
    {
    public:
        using ptr = std::shared_ptr<BaseConnection>;
        virtual void send(const BaseMessage::ptr &msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0; // 判断是否是一个是、正常连接
    };

    using ConnectionCallback = std::function<void(const BaseConnection::ptr &)>;
    using CloseCallback = std::function<void(const BaseConnection::ptr &)>;
    using MessageCallback = std::function<void(const BaseConnection::ptr &, const BaseMessage::ptr &)>;

    class BaseServer
    {
    public:
        using ptr = std::shared_ptr<BaseServer>;
        virtual void setConnectionCallback(const ConnectionCallback &cb) { _cb_connection = cb; }
        virtual void setCloseCallback(const CloseCallback &cb) { _cb_close = cb; }
        virtual void setMessageCallback(const MessageCallback &cb) { _cb_message = cb; }
        virtual void start() = 0;

    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };

    class BaseClient
    {
    public:
        using ptr = std::shared_ptr<BaseClient>;
        virtual void setConnectionCallback(const ConnectionCallback &cb) { _cb_connection = cb; }
        virtual void setCloseCallback(const CloseCallback &cb) { _cb_close = cb; }
        virtual void setMessageCallback(const MessageCallback &cb) { _cb_message = cb; }
        virtual bool connect() = 0;
        virtual void send(const BaseMessage::ptr &msg) = 0;
        virtual void shutdown() = 0;
        virtual BaseConnection::ptr connection() = 0; // 获取连接
        virtual bool connected() = 0;

    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };
};